diff options
| author | diogo464 <[email protected]> | 2025-08-11 11:51:39 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2025-08-11 11:51:39 +0100 |
| commit | 4af66f418b6837b6441b4e8eaf2d8ede585238b9 (patch) | |
| tree | 34a4e913a2848515166b2ac0489794419a33bfcc /frontend/app/drive/[...path]/page.tsx | |
| parent | 0d3488a3811c8d58bd570af64cc29840df9ba439 (diff) | |
snapshot
Diffstat (limited to 'frontend/app/drive/[...path]/page.tsx')
| -rw-r--r-- | frontend/app/drive/[...path]/page.tsx | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/frontend/app/drive/[...path]/page.tsx b/frontend/app/drive/[...path]/page.tsx new file mode 100644 index 0000000..75a1bb1 --- /dev/null +++ b/frontend/app/drive/[...path]/page.tsx | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | import { Drive_ls, Drive_basename, Drive_parent } from "@/lib/drive" | ||
| 2 | import { formatSize } from "@/lib/utils" | ||
| 3 | import Link from "next/link" | ||
| 4 | import { cookies } from 'next/headers'; | ||
| 5 | import { Auth_get_user } from "@/lib/auth"; | ||
| 6 | |||
| 7 | interface DrivePageProps { | ||
| 8 | params: Promise<{ | ||
| 9 | path: string[] | ||
| 10 | }> | ||
| 11 | } | ||
| 12 | |||
| 13 | export default async function DrivePage({ params }: DrivePageProps) { | ||
| 14 | // Await params as required by Next.js 15 | ||
| 15 | const { path } = await params | ||
| 16 | |||
| 17 | const user = await Auth_get_user(); | ||
| 18 | console.log(user); | ||
| 19 | |||
| 20 | // Construct the full path from params | ||
| 21 | const fullPath = path ? `/${path.join('/')}` : "" | ||
| 22 | |||
| 23 | const entries = await Drive_ls(fullPath, false) | ||
| 24 | |||
| 25 | // Check if we have a parent directory | ||
| 26 | const parentDir = Drive_parent(fullPath) | ||
| 27 | const parentPath = path && path.length > 1 | ||
| 28 | ? `/drive/${path.slice(0, -1).join('/')}` | ||
| 29 | : path && path.length === 1 | ||
| 30 | ? '/drive' | ||
| 31 | : null | ||
| 32 | |||
| 33 | // Create entries with optional parent directory at top | ||
| 34 | const allEntries = [] | ||
| 35 | if (parentDir !== null && parentPath !== null) { | ||
| 36 | allEntries.push({ | ||
| 37 | path: '(parent)', | ||
| 38 | type: 'dir' as const, | ||
| 39 | lastmod: 0, | ||
| 40 | blob: null, | ||
| 41 | size: null, | ||
| 42 | author: '', | ||
| 43 | isParent: true, | ||
| 44 | parentPath | ||
| 45 | }) | ||
| 46 | } | ||
| 47 | |||
| 48 | // Sort entries: directories first, then files, both alphabetically | ||
| 49 | const sortedEntries = entries.sort((a, b) => { | ||
| 50 | // First sort by type (directories before files) | ||
| 51 | if (a.type !== b.type) { | ||
| 52 | return a.type === 'dir' ? -1 : 1 | ||
| 53 | } | ||
| 54 | // Then sort alphabetically by path | ||
| 55 | return a.path.localeCompare(b.path) | ||
| 56 | }) | ||
| 57 | |||
| 58 | allEntries.push(...sortedEntries) | ||
| 59 | |||
| 60 | return ( | ||
| 61 | <div className="min-h-screen bg-background"> | ||
| 62 | <div className="container mx-auto p-4"> | ||
| 63 | <Link href="/drive" className="inline-block mb-6"> | ||
| 64 | <h1 className="text-2xl font-bold text-foreground hover:text-blue-600 dark:hover:text-blue-400 transition-colors cursor-pointer">FCTDrive</h1> | ||
| 65 | </Link> | ||
| 66 | |||
| 67 | <div className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden"> | ||
| 68 | <div className="overflow-x-auto"> | ||
| 69 | <table className="w-full"> | ||
| 70 | <thead className="bg-gray-50 dark:bg-gray-700"> | ||
| 71 | <tr> | ||
| 72 | <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"> | ||
| 73 | Name | ||
| 74 | </th> | ||
| 75 | <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"> | ||
| 76 | Size | ||
| 77 | </th> | ||
| 78 | <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"> | ||
| 79 | Author | ||
| 80 | </th> | ||
| 81 | <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider"> | ||
| 82 | Modified | ||
| 83 | </th> | ||
| 84 | </tr> | ||
| 85 | </thead> | ||
| 86 | <tbody className="divide-y divide-gray-200 dark:divide-gray-600"> | ||
| 87 | {allEntries.map((entry, index) => ( | ||
| 88 | <tr | ||
| 89 | key={entry.path} | ||
| 90 | className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors" | ||
| 91 | > | ||
| 92 | <td className="px-4 py-4 whitespace-nowrap"> | ||
| 93 | <div className="flex items-center"> | ||
| 94 | <div className="flex-shrink-0 h-5 w-5 mr-3"> | ||
| 95 | {entry.type === 'dir' ? ( | ||
| 96 | <div className="h-5 w-5 text-blue-500">📁</div> | ||
| 97 | ) : ( | ||
| 98 | <div className="h-5 w-5 text-gray-400">📄</div> | ||
| 99 | )} | ||
| 100 | </div> | ||
| 101 | {entry.type === 'dir' ? ( | ||
| 102 | <Link | ||
| 103 | href={(entry as any).isParent ? (entry as any).parentPath : `/drive${entry.path}`} | ||
| 104 | className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline" | ||
| 105 | > | ||
| 106 | {(entry as any).isParent ? '(parent)' : Drive_basename(entry.path)} | ||
| 107 | </Link> | ||
| 108 | ) : ( | ||
| 109 | <Link | ||
| 110 | href={`/blob/${entry.blob}?filename=${encodeURIComponent(Drive_basename(entry.path))}`} | ||
| 111 | className="text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline" | ||
| 112 | > | ||
| 113 | {Drive_basename(entry.path)} | ||
| 114 | </Link> | ||
| 115 | )} | ||
| 116 | </div> | ||
| 117 | </td> | ||
| 118 | <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300"> | ||
| 119 | {formatSize(entry.size)} | ||
| 120 | </td> | ||
| 121 | <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300"> | ||
| 122 | {entry.author} | ||
| 123 | </td> | ||
| 124 | <td className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-300"> | ||
| 125 | {new Date(entry.lastmod * 1000).toLocaleString()} | ||
| 126 | </td> | ||
| 127 | </tr> | ||
| 128 | ))} | ||
| 129 | </tbody> | ||
| 130 | </table> | ||
| 131 | </div> | ||
| 132 | </div> | ||
| 133 | </div> | ||
| 134 | </div> | ||
| 135 | ) | ||
| 136 | } | ||
